package com.shadow.demo.dictionary.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shadow.demo.dictionary.common.ParseUtil;
import com.shadow.demo.dictionary.dto.DicDTO;
import com.shadow.demo.dictionary.dto.DicItemDTO;
import com.shadow.demo.dictionary.entity.DicEntity;
import com.shadow.demo.dictionary.entity.DicItemEntity;
import com.shadow.demo.dictionary.enums.DicEnum;
import com.shadow.demo.dictionary.mapper.DicMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
@Transactional
public class DicService extends BaseService<DicMapper, DicEntity> implements IService<DicEntity> {

    private final DicItemService dicModelService;
    private final DicMapper dicMapper;

    DicService(DicItemService dicModelService, DicMapper dicMapper) {
        this.dicModelService = dicModelService;
        this.dicMapper = dicMapper;
    }

//    public File exportDic(String[] dicIds) {
//        List<DicDTO> dicList = listDicByIds(dicIds);
//        String[] dicNames = new String[dicList.size()];
//        for (int i = 0; i < dicList.size(); i++) {
//            dicNames[i] = dicList.get(i).getName();
//        }
//        Map<String, List<DicItemDTO>> treeDicItem = treeDicItemsByDicNames(dicNames);
//        for (Map.Entry<String, List<DicItemDTO>> entry : treeDicItem.entrySet()) {
//            for (DicDTO dicDTO : dicList) {
//                if (Objects.equals(dicDTO.getName(), entry.getKey())) {
//                    dicDTO.setItems(entry.getValue());
//                }
//            }
//        }
//        String jsonData = JSONArray.toJSONString(dicList);
//        String fileName = "数据字典.json";
//        // 创建临时文件
//        File file = PathUtil.createTmpFile(fileName);
//        IoUtil.writeText(jsonData, file);
//        return file;
//    }
//    public List<DicItemDTO> getDicItemByNamePath(String xpath, int fillDepth) {
//        List<DicItemDTO> result = new ArrayList<>();
//        if (xpath == null || xpath.length() == 0) {
//            return new ArrayList<>();
//        }
//
//        String[] pathList = xpath.split("/");
//        //int fillOffset = 0;
//        List<DicItemDTO> dicItems = treeDicItemByDicName(pathList[0], "/");
//        if (CollectionUtils.isEmpty(dicItems)) {
//            return result;
//        }
//        if (pathList.length == 1) {
//            return dicItems;
//        } else {
//            DicItemDTO dicItemDTO = fiterDicItemByName(dicItems, pathList[1]);
//            for (int i = 2; i < pathList.length; i++) {
//                if (dicItemDTO == null) {
//                    break;
//                }
//                dicItemDTO = fiterDicItemByName(dicItemDTO.getChildren(), pathList[i]);
//            }
//            if (dicItemDTO != null) {
//                result.add(dicItemDTO);
//            }
//        }
//        return result;
//    }
//    public DicItemDTO fiterDicItemByName(List<DicItemDTO> dicItems, String name) {
//        for (DicItemDTO dicItem : dicItems) {
//            if (dicItem.getName().equals(name)) {
//                return dicItem;
//            }
//        }
//        return null;
//    }
//    private void closeQuietly(Session session) {
//        try {
//            if (session != null && session.isOpen()) {
//                session.close();
//            }
//        } catch (Exception e) {
//            log.error("close session error", e);
//        }
//    }

    public List<DicItemDTO> treeDicItemByDicId(String dicId, String parentId) {
        DicEntity dic = getById(dicId);
        List<DicItemDTO> list = treeDicItem(dic, parentId);
        return treeDicItem(list);
    }

    public List<DicItemDTO> treeDicItemByDicName(String dicName, String parentId) {
        DicEntity dic = getDicByName(dicName, 1);
        if (dic == null) {
            return new ArrayList<>();
        }
        List<DicItemDTO> list = treeDicItem(dic, parentId);
        return treeDicItem(list);
    }

    public List<DicDTO> dicNamepathMulti(String xpath, int fillDepth) {
        String[] xpaths = xpath.split(",");
        List<DicDTO> resp = new ArrayList<>();
        for (String dicName : xpaths) {
            List<DicItemDTO> dicItems = treeDicItemByDicName(dicName, "/");
            DicDTO dicDTO = new DicDTO();
            dicDTO.setName(dicName);
            dicDTO.setItems(dicItems);
            resp.add(dicDTO);
        }
        return resp;
    }

    public List<DicItemDTO> listDicItem(DicEntity dic, String parentId) {
        DicDTO dicDTO = getDicDTO(dic);
        List<DicItemDTO> dicItemDTOs = null;
        if (dicDTO != null) {
            if (DicEnum.RootId.equals(parentId) || StringUtils.isEmpty(parentId)) {
                dicItemDTOs = dicDTO.getItems();
            } else {
                dicItemDTOs = dicDTO.getItems();
                DicItemDTO dicItem = findDicItem(dicItemDTOs, parentId);
                if (dicItem != null) {
                    dicItemDTOs = dicItem.getChildren();
                }
            }
        }
        if (dicItemDTOs == null) {
            dicItemDTOs = new ArrayList<>();
        }
        return dicItemDTOs;
    }

    private DicItemDTO findDicItem(List<DicItemDTO> dicItems, String id) {
        DicItemDTO item = null;
        for (DicItemDTO dicItem : dicItems) {
            if (dicItem.getId().equals(id)) {
                item = dicItem;
            } else if (dicItem.getChildren() != null) {
                item = findDicItem(dicItem.getChildren(), id);
            }
            if (item != null) {
                break;
            }
        }
        return item;
    }

    /**
     * 通过id获取字典
     * @param id id
     * */
    public DicDTO getDicById(final String id) {
        DicEntity dic = getById(id);
        return getDicDTO(dic);
    }

    /**
     * 通过id获取字典
     * @param idList id
     * */
    public List<DicEntity> listDicByIds(final List<String> idList) {
        if (CollectionUtils.isNotEmpty(idList)) {
            LambdaQueryWrapper<DicEntity> wrapper = new LambdaQueryWrapper<DicEntity>()
                    .in(DicEntity::getId, idList);
            return dicMapper.selectList(wrapper);
        }
        return Collections.emptyList();
    }

    /**
     * 通过名称获取字典
     * @param name 名称
     * */
    public DicEntity getDicByName(final String name, int temp) {
        LambdaQueryWrapper<DicEntity> wrapper = new LambdaQueryWrapper<DicEntity>()
                .eq(DicEntity::getName, name)
                .last("limit 1");
        return dicMapper.selectOne(wrapper);
    }

    public DicDTO getDicByName(final String name) {
        LambdaQueryWrapper<DicEntity> wrapper = new LambdaQueryWrapper<DicEntity>()
                .eq(DicEntity::getName, name)
                .last("limit 1");
        DicEntity dicEntity = dicMapper.selectOne(wrapper);
        return getDicDTO(dicEntity);
    }

    /**
     * 通过名称获取字典2
     * @param nameList 名称
     * */
    public List<DicEntity> getDicByNameList(final List<String> nameList) {
        if (CollectionUtils.isNotEmpty(nameList)) {
            LambdaQueryWrapper<DicEntity> wrapper = new LambdaQueryWrapper<DicEntity>()
                    .in(DicEntity::getName, nameList);
            return dicMapper.selectList(wrapper);
        }
        return Collections.emptyList();
    }

    public List<DicItemDTO> listDicItemByDicNameNew(String dicName, String parentId, Map<String, Object> param) {
        DicEntity dic = getDicByName(dicName, 1);
        if (dic == null) {
            return null;
        }
        //这一步开发分类，如果是常规字典查询跳转常规查询，如果是sql查询跳转sql查询。这里默认走常规字典查询，除非特别指出sql查询
        if (StringUtils.isNotEmpty(dic.getType()) && StringUtils.equals(dic.getType(), DicEnum.DicType_Sql)) {
            return listDicItemBySQL(dic, param);
        } else {
            //这里是默认值
            List<DicItemDTO> list = treeDicItem(dic, "");
            return treeDicItem(list);
        }
    }

    /**
     * 通过id获取字典3
     * @param dicNames 名称
     * */
    public List<DicEntity> listDicByIds(final String... dicNames) {
        return getDicByNameList(Arrays.asList(dicNames));
    }

    /**
     * 保存字典
     * */
    @CacheEvict(
            value = "dicItemByDicId",
            key = "#dic.id",
            condition = "#dic!=null&&#dic.id!=null"
    )
    public DicEntity saveDic(final DicEntity dic) {
        dic.setModifyTime(Calendar.getInstance().getTime());
        if (dic.getSortNo() == null) {
            dic.setSortNo(getMaxDicSortNo());
        }
        dicMapper.insert(dic);
        return dic;
    }

    /**
     * 查询字典最大排序
     * */
    public Integer getMaxDicSortNo() {
        Integer max = dicMapper.getMaxDicSortNo();
        log.info("查询字典最大排序, max: {}", max);
        return max == null ? 1 : max + 1;
    }

    private DicDTO getDicDTO(DicEntity dic) {
        if (dic != null) {
            DicDTO dicDTO = ParseUtil.parseValue(DicDTO.class, dic);
            dicDTO.setItems(treeDicItem(dic, ""));
            return dicDTO;
        }
        return null;
    }

    public List<DicItemDTO> treeDicItem(DicEntity dic, String parentId) {
        List<DicItemDTO> dicItemDTOs = null;
        if (DicEnum.DicType_Sql.equals(dic.getType())) {
            dicItemDTOs = listDicItemBySQL(dic, new HashMap<>());
        } else {
            List<DicItemEntity> dicItems = dicModelService.listDicItemByDicIds(Collections.singletonList(dic.getId()));
            dicItemDTOs = ParseUtil.parseList(DicItemDTO.class, dicItems);
        }
        return dicItemDTOs;
    }

    /**
     * 重载方法，多了sql查询传参功能，对原来的功能进行完善
     * @param dic   字典对象
     * @param param 查询参数
     * @return xx
     */
    private List<DicItemDTO> listDicItemBySQL(DicEntity dic, Map<String, Object> param) {
        List<DicItemDTO> dicItems = null;
        if (StringUtils.isNotBlank(dic.getExt())) {
            //字典配置的sql原文
            String ext = dic.getExt();
            if (param != null && !param.isEmpty()) {
                //传参不为空，需要进行字典值替换
                for (Map.Entry<String, Object> entry : param.entrySet()) {
                    if (ext.contains(entry.getKey())) {
                        ext = ext.replace((":" + entry.getKey()), ParseUtil.getString(entry.getValue(), ""));
                    }
                }
            }
//            SessionFactory sessionFactory = SessionFactoryManager.getSessionFactory(dic.getRepositoryName());
//            Session session = sessionFactory.getCurrentSession();
            List<?> list = null;
//            if (session == null) {
//                try {
//                    session = sessionFactory.openSession();
//                    list = session.createSQLQuery(ext).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).getResultList();
//                } catch (Exception e) {
//                    LogUtil.error("SQL查询异常！", e);
//                } finally {
//                    closeQuietly(session);
//                }
//            } else {
//                list = session.createSQLQuery(ext).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).getResultList();
//            }
            List<DicItemDTO> items = new ArrayList<>();
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    Map<String, Object> item = (Map<String, Object>) list.get(i);
                    DicItemDTO dicItem = new DicItemDTO();
                    dicItem.setChildren(new ArrayList<>());
                    dicItem.setDicId(dic.getId());
                    dicItem.setId(ParseUtil.getString(item.get("id"), ""));
                    dicItem.setName(ParseUtil.getString(item.get("name"), ""));
                    dicItem.setValue(ParseUtil.getString(item.get("value"), null));
                    dicItem.setParentId(ParseUtil.getString(item.get("parentId"), null));
                    dicItem.setSortNo(ParseUtil.getInteger(item.get("sortNo"), i + 1));
                    items.add(dicItem);
                }
            }
            dicItems = treeDicItem(items);
        }
        if (dicItems == null) {
            dicItems = new ArrayList<>();
        }
        return dicItems;
    }

    private List<DicItemDTO> treeDicItem(List<DicItemDTO> dicItems) {
        Map<String, DicItemDTO> dicItemMap = new HashMap<>();
        for (DicItemDTO item : dicItems) {
            dicItemMap.put(item.getId(), item);
        }
        List<DicItemDTO> items = new ArrayList<>();
        for (DicItemDTO item : dicItems) {
            String parentId = item.getParentId();
            if (dicItemMap.containsKey(parentId)) {
                DicItemDTO itemDTO = dicItemMap.get(parentId);
                List<DicItemDTO> children = itemDTO.getChildren();
                if (children != null) {
                    children.add(item);
                } else {
                    List<DicItemDTO> childrenList = new ArrayList<>();
                    childrenList.add(item);
                    itemDTO.setChildren(childrenList);
                }
            } else {
                items.add(item);
            }
        }
        for (DicItemDTO item : items) {
            item.setParentId(DicEnum.RootId);
        }
        return items;
    }
}
